#include "srreviewauiditwidget.h"

#include <thread>

#include <QSpinBox>
#include <QTextCodec>
#include <QProcess>
#include <QTimer>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QCheckBox>
#include <QLineEdit>
#include <QLabel>
#include <QJsonDocument>
#include <QTableView>
#include <QHeaderView>
#include <QStandardItemModel>
#include <QFileDialog>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QMessageBox>
#include <QDebug>

#include <OEMessageBox>
#include <OENotifyMessageBox>


/// private xls lib
#include <oeexcelreader.h>
#include <oeexcelwriter.h>

#include <auditcryptogram.h>

#include "srtransactionwidget.h"
#include "srdatabase.h"


#define TABLE_IDX       (0)
#define TABLE_AUDIT_ID  (1)
#define TABLE_STATUS    (2)
#define TABLE_SUM       (3)
#define TABLE_TXID      (4)
#define TABLE_CRT_TIME  (5)
#define TABLE_COUNT     (6)




SRReviewAuditWidget::SRReviewAuditWidget(QWidget *parent)
    : QWidget(parent),
    bThreadReadExcel_(false)
{
    QVBoxLayout * layout = new QVBoxLayout();
    QHBoxLayout * layout_navigation = new QHBoxLayout();
    QHBoxLayout * layout_query = new QHBoxLayout();
    QHBoxLayout * layout_operator = new QHBoxLayout();
    QHBoxLayout * layout_bottom = new QHBoxLayout();


    // 详情信息页面
    boxPageNum_ = new QSpinBox();
    pageAuditInfo_ = new SRTransactionWidget();
//    pageAuditInfo_->setMinimumSize(1024,700);

    // bottom
    labAuditCount_ = new QLabel(tr("审核数: 0"));
    labAuditCount_->setObjectName(tr("审核数: %1"));


    QPushButton* btn_export = new QPushButton(tr("导出"));
    btnAllSelect_  = new QPushButton(tr("全  选"));
    QLabel* lab_audit_num = new QLabel(tr("审核编号:"));
    edtAuditNum_ = new QLineEdit();
    QLabel* lab_page = new QLabel(tr("页数:"));
    QRegExp regQuote("[0-9a-zA-Z]{1,36}");
    QRegExpValidator* quote_validator = new QRegExpValidator(regQuote, this);
    edtAuditNum_->setValidator(quote_validator);
    QPushButton* btn_query = new QPushButton(tr("查询"));
    btn_query->setObjectName("auditQuery");

    tableView_ = new QTableView();
    model_ = new QStandardItemModel();
    tableView_->setModel(model_);

    QHeaderView *headerGoods = tableView_->horizontalHeader();
    //SortIndicator为水平标题栏文字旁边的三角指示器
    headerGoods->setSortIndicator(0, Qt::AscendingOrder);
    headerGoods->setSortIndicatorShown(true);
    connect(headerGoods, SIGNAL(sectionClicked(int)),
            tableView_, SLOT (sortByColumn(int)));
    connect(boxPageNum_, SIGNAL(valueChanged(int)),
            this, SLOT(onUpdate(int)));
    connect(btnAllSelect_, &QPushButton::clicked,
            this, [=] {
        if (model_->rowCount() == 0) {
            return;
        }
        if (btnAllSelect_->text() == "全  选") {
            for (int i = 0; i < model_->rowCount(); ++i)
                model_->item(i)->setCheckState(Qt::CheckState::Checked);
            btnAllSelect_->setText("取消全选");
        }
        else {
            for (int i = 0; i < model_->rowCount(); ++i)
                model_->item(i)->setCheckState(Qt::CheckState::Unchecked);
            btnAllSelect_->setText("全  选");
        }

    });

    // model 初始化
    model_->setColumnCount(TABLE_COUNT);
    model_->setHeaderData(TABLE_IDX, Qt::Horizontal, tr("序号"));
    model_->setHeaderData(TABLE_AUDIT_ID, Qt::Horizontal, tr("审核编号"));
    model_->setHeaderData(TABLE_STATUS, Qt::Horizontal, tr("审核状态"));
    model_->setHeaderData(TABLE_SUM, Qt::Horizontal, tr("含交易数"));
    model_->setHeaderData(TABLE_TXID, Qt::Horizontal, tr("txid"));
    model_->setHeaderData(TABLE_CRT_TIME, Qt::Horizontal, tr("审批时间"));

    // tableview 初始化
    tableView_->setSelectionBehavior(QAbstractItemView::SelectRows); // 选中整行
    tableView_->setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection); // 只能单选
    tableView_->setEditTriggers(QTableView::EditTrigger::NoEditTriggers);
    tableView_->setAlternatingRowColors(true);
    tableView_->setMouseTracking(true);

    tableView_->setColumnWidth(TABLE_IDX, 60);
    tableView_->setColumnWidth(TABLE_AUDIT_ID, 160);
    tableView_->setColumnWidth(TABLE_STATUS, 60);
    tableView_->setColumnWidth(TABLE_SUM, 60);
    tableView_->setColumnWidth(TABLE_TXID, 420);
    tableView_->setColumnWidth(TABLE_CRT_TIME, 160);
    tableView_->horizontalHeader()->setSectionResizeMode(TABLE_IDX,QHeaderView::Interactive);
    tableView_->horizontalHeader()->setSectionResizeMode(TABLE_AUDIT_ID,QHeaderView::Stretch);
    tableView_->horizontalHeader()->setSectionResizeMode(TABLE_STATUS,QHeaderView::Interactive);
    tableView_->horizontalHeader()->setSectionResizeMode(TABLE_SUM,QHeaderView::Interactive);
    tableView_->horizontalHeader()->setSectionResizeMode(TABLE_TXID,QHeaderView::Stretch);
    tableView_->horizontalHeader()->setSectionResizeMode(TABLE_CRT_TIME,QHeaderView::Interactive);


//    tableView_->setColumnWidth(0, 60);
//    tableView_->setColumnWidth(2, 60);
//    tableView_->setColumnWidth(3, 60);
//    tableView_->setColumnWidth(4, 420);
//    tableView_->setColumnWidth(5, 160);
//    tableView_->horizontalHeader()->setSectionResizeMode(1,QHeaderView::Stretch);
#ifdef QT_DEBUG
    for(int i = 0; i < 10; ++i) {
        QStandardItem *item = new QStandardItem();
        item->setCheckable(true);
        item->setText(QString::number(i));
        item->setCheckState(Qt::Unchecked);
        model_->setItem(i, 0, item);
        model_->setItem(i, 1, new QStandardItem("654654654"));
        model_->setItem(i, 2, new QStandardItem("admin"));
        model_->setItem(i, 3, new QStandardItem("admin"));
        model_->setItem(i, 4, new QStandardItem("admin"));
        model_->setItem(i, 5, new QStandardItem("admin"));
    }
#else
#endif

    // 信号链接
    connect(btn_query, &QPushButton::clicked,
            this, &SRReviewAuditWidget::onQuery);
    connect(btn_export, &QPushButton::clicked,
            this, &SRReviewAuditWidget::onExportXlsClick);
    connect(tableView_, &QTableView::doubleClicked,
            this, &SRReviewAuditWidget::onRowDoubleClicked);

    // Excel导入消息
    OENotifyManager *manager = new OENotifyManager();
    connect(this, &SRReviewAuditWidget::sigExcelDone,
            manager, [manager](int a, int b){
        QString title = "Excel导入成功";
        if (a == 0 || b == 0) {
            title = "Excel导入非法";
        }
        QString msg = QString("交易数据(条): %1  审核总数(笔): %2")
                            .arg(a).arg(b);
        manager->notify(title, msg, ":/lab/logo", "");
    });
    // 签名消息
    connect(this, &SRReviewAuditWidget::sigSignDone,
            manager, [manager](int a, int b){
        QString title = "签名完毕";
        if (a == 0 || b == 0) {
            title = "非法签名";
            SRDatabase::DB()->writeOperateLog("进行了一次非法的签名行为",1);
        }

        QString msg = QString("签名成功: %1  签名失败: %2")
                            .arg(a).arg(b);
        manager->notify(title, msg, ":/lab/logo", "");
    });


    // 大小
    btn_export->setFixedSize(64,24);
    btnAllSelect_->setFixedSize(87,24);
    edtAuditNum_->setFixedSize(87,24);
    btn_query->setFixedSize(58,24);
    boxPageNum_->setFixedSize(64,24);




    // 布局
    layout_query->addWidget(lab_audit_num,0,Qt::AlignLeft);
    layout_query->addWidget(edtAuditNum_,0,Qt::AlignLeft);
    layout_query->addWidget(btn_query,0,Qt::AlignLeft);

    layout_operator->addWidget(btnAllSelect_,0,Qt::AlignRight);
    layout_operator->addWidget(btn_export,0,Qt::AlignRight);

    layout_navigation->addLayout(layout_query);
    layout_navigation->addStretch();
    layout_navigation->addLayout(layout_operator);

    layout_bottom->addWidget(labAuditCount_, 0, Qt::AlignLeft);
    layout_bottom->addSpacing(20);
    layout_bottom->addWidget(lab_page,0,Qt::AlignLeft);
    layout_bottom->addWidget(boxPageNum_, 0, Qt::AlignLeft);
    layout_bottom->addStretch();

    layout->addLayout(layout_navigation);
    layout->addWidget(tableView_);
    layout->addLayout(layout_bottom);

    setLayout(layout);
}

bool SRReviewAuditWidget::isBusy()
{
    if (bThreadReadExcel_ || bThreadSign_)
        return true;
    return false;
}

void SRReviewAuditWidget::showEvent(QShowEvent *event)
{
    Q_UNUSED(event);
//    if (model_->rowCount() > 0)
//        model_->removeRows(0, model_->rowCount());
    onUpdate(boxPageNum_->value());
}

void SRReviewAuditWidget::hideEvent(QShowEvent *event)
{
    Q_UNUSED(event);
    pageAuditInfo_->hide();
}

void SRReviewAuditWidget::onExportXlsClick() {
    // 验证是否有选中的数据
    bool bflag = false;

    for (int i = 0; i < model_->rowCount(); ++i) {
        if (model_->item(i,0)->checkState()
                == Qt::CheckState::Checked) {
            bflag = true;
            break;
        }
    }
    if (!bflag) {
        OEMessageBox::BriefMessage(this,"请选择交易信息");
        return;
    }



    static QString last_open_dir = "..";
    QString file_name = QFileDialog::getSaveFileName(this, tr("打开待审核的Excecl表格"),
                                 last_open_dir, tr("Excel表格文件(*.xls)"));
    if (file_name.isEmpty()) {
        return ;
    }


    // @remark： 后面改成异步

    OEExcelWriter writer;
    writer.CreateWorkSheet("withdraw cash");

    int r = 1;
    writer.SetCellText(0,0,"audit_id",true);
    writer.SetCellText(0,1,"bitcoin_hex",true);
    writer.SetCellText(0,2,"bitcoin",true);
    for (int i = 0; i < model_->rowCount(); ++i) {
        if (model_->item(i,0)->checkState()
                == Qt::CheckState::Checked) {
            QString id_key = model_->item(i,0)->text();
            QString audit_id = model_->item(i,TABLE_AUDIT_ID)->text();
            stSignData temp_sign_data = mapBroadcasting_.find(id_key).value();
            writer.SetCellText(r,0,audit_id.toUtf8().data(),false);
            writer.SetCellText(r,1,temp_sign_data.hex.toUtf8().data(),false);
            writer.SetCellText(r,2,temp_sign_data.data.toUtf8().data(),false);
            ++r;
            // 更新为已导出
            SRDatabase::DB()->upXlsRecordExport(audit_id);
            model_->item(i, TABLE_STATUS)->setText("已导出");
        }
    }

    btnAllSelect_->setText("全  选");

    // 将导出的写入本地数据库

    // window下不能输出utf路径
#ifdef Q_OS_WIN32
    QTextCodec* pCodec = QTextCodec::codecForName("gbk");
    if(!pCodec)
        qWarning("codec convert gb2312 failed!");

    QByteArray arr = pCodec->fromUnicode(file_name);

    writer.SaveExcelFile(arr.data());
#else
    writer.SaveExcelFile(file_name.toUtf8().data());
#endif
}

void SRReviewAuditWidget::onUpdate(int idx)
{
    idx = idx - 1;
    if (idx <= 0) {
        boxPageNum_->setValue(1);
        idx = 0;
    }
    const int& PAGE_COUNT = 20;

    int ret_xls_size = SRDatabase::DB()->getXlsRecordSize();
    labAuditCount_->setText(labAuditCount_->objectName().arg(ret_xls_size));


    QList<SRDatabase::stXlsRecord> list_xls;
    int ret = SRDatabase::DB()->getXlsRecord(PAGE_COUNT*idx,
                                   idx*PAGE_COUNT+PAGE_COUNT,
                                   list_xls);
    if (ret != 0) {
        return;
    }

    if (list_xls.size() == 0) {
//        boxPageNum_->valueChanged(idx);
        if (idx == 0)
            return;
        boxPageNum_->setValue(idx);
        return;
    }

    mapBroadcasting_.clear();


    model_->removeRows(0, model_->rowCount());



    for (auto item : list_xls) {

        int transaction_count = 0;
        QString txid = "";
        // decode item.signData;
        QJsonParseError jsonError;
        QJsonDocument doucment = QJsonDocument::fromJson(item.sigData.toUtf8(), &jsonError);
        if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError)) {
            if (doucment.isObject()) {
                QJsonObject object = doucment.object();

                if (object.contains("txid")) {
                    txid = object.value("txid").toString();
                }

                if (object.contains("vout")) {
                    QJsonArray vout_arr = object.value("vout").toArray();
                    if (!vout_arr.isEmpty())
                        transaction_count = vout_arr.size();
                }
            }
        }

        //

        insertModelData(item.id,
                        item.auditId,
                        item.isExport,
                        QString::number(transaction_count),
                        txid,
                        item.crtTime);
        mapBroadcasting_.insert(item.id,stSignData(item.sigData,item.sigDataHex));
    }
}


void SRReviewAuditWidget::onRowDoubleClicked(const QModelIndex &_item)
{
    pageAuditInfo_->setAuditId(model_->item(_item.row(),TABLE_AUDIT_ID)->text());
    QMap<QString,stSignData>::iterator audit_data =
            mapBroadcasting_.find(model_->item(_item.row(), TABLE_IDX)->text());
    pageAuditInfo_->setAuditData(audit_data->data);
    pageAuditInfo_->show();
    pageAuditInfo_->raise();
    pageAuditInfo_->setFocus();
}



void SRReviewAuditWidget::onQuery() {
    // @remakr : pan
    if (model_->rowCount() == 0) {
        return;
    }
    QString choose_txt = edtAuditNum_->text().trimmed();

    if (!choose_txt.isEmpty()) {
        QList<QStandardItem*> temp_list = model_->findItems(
                   choose_txt, Qt::MatchContains, TABLE_AUDIT_ID);

        QList<QStandardItem*>::iterator item = temp_list.begin();
        for (;item != temp_list.end(); ++item) {
            int old = tableView_->currentIndex().row();
            if ((*item)->row() > old) {
                tableView_->selectRow((*item)->row());
                break;
            }
        }
        if (item == temp_list.end()) {
            if (temp_list.size() != 0)
                tableView_->selectRow(temp_list.at(0)->row());
        }
    }

}

void SRReviewAuditWidget::insertModelData(const QString &id,
                                          const QString &audit_id,
                                          const int &is_export,
                                          const QString &transaction_count,
                                          const QString &txid,
                                          const QString &crt_time)
{

    QStandardItem *item = new QStandardItem();
    item->setCheckable(true);
    item->setText(id);
    item->setCheckState(Qt::Unchecked);

    int idx = model_->rowCount();

    model_->setItem(idx, TABLE_IDX, item);
    model_->setItem(idx, TABLE_AUDIT_ID, new QStandardItem(audit_id));
    if (is_export == 0) {
        model_->setItem(idx, TABLE_STATUS, new QStandardItem(tr("未导出")));
    }
    else {
        model_->setItem(idx, TABLE_STATUS, new QStandardItem(tr("已导出")));
    }

    model_->setItem(idx, TABLE_SUM, new QStandardItem(transaction_count));
    model_->setItem(idx, TABLE_TXID, new QStandardItem(txid));
    model_->setItem(idx, TABLE_CRT_TIME, new QStandardItem(crt_time));

    for (int i = 0; i < TABLE_COUNT; ++i)
        model_->item(idx,i)->setTextAlignment(Qt::AlignCenter);
}

